from IPython.display import Image
#Image(filename='/Users/oldemarrodriguez/Mi unidad/Análisis de Datos II -SEP 2022/Tema 3 - 2022/Curva ROC y Probabilidad de Corte/logo.png')
Image(filename='/Users/oldemarrodriguez/Google Drive/Análisis de Datos II -SEP 2022/Tema 3 - 2022/Curva ROC y Probabilidad de Corte/logo.png')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
Tamaño de los gráficos
figsize = (6,4)
dpi = 150
def f(x):
return 2 * x * x * np.cos(x) - 5 * x
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
t1 = np.arange(-5.0, 5.0, 0.1)
ax.set_xlim(-5, 5)
ax.set_ylim(-45, 45)
ax.plot(t1, f(t1))
x = [-1.0]
y = [f(x[0])]
ax.plot(x,y,'ro')
print("X = ", x)
print("Y = ", y)
X = [-1.0] Y = [6.0806046117362795]
# La derivada de f (la pendiente)
def df(x):
return 4 * x * np.cos(x) - 2 * x * x * np.sin(x) - 5
pendiente = df(x[0])
print("Pendiente: ", pendiente)
eta = 0.05
x.append(x[0] - eta * pendiente)
y.append(f(x[0] - eta * pendiente))
print("X = ", x)
print("Y = ", y)
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.set_xlim(-5, 5)
ax.set_ylim(-45, 45)
ax.plot(t1, f(t1))
ax.plot(x,y,'ro')
Pendiente: -5.478267253856766 X = [-1.0, -0.7260866373071617] Y = [6.0806046117362795, 4.418893422871324]
[<matplotlib.lines.Line2D at 0x7f7eb80d15b0>]
x.append(x[1] - eta * df(x[1]))
y.append(f(x[1] - eta * df(x[1])))
print("X = ", x)
print("Y = ", y)
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.set_xlim(-5, 5)
ax.set_ylim(-45, 45)
ax.plot(t1, f(t1))
ax.plot(x,y,'ro')
X = [-1.0, -0.7260866373071617, -0.4024997370140509] Y = [6.0806046117362795, 4.418893422871324, 2.310617230890063]
[<matplotlib.lines.Line2D at 0x7f7ecc00a850>]
eta = 0.05
x = [-1.0]
y = [f(x[0])]
for i in range(20):
x.append(x[i] - eta * df(x[i]))
y.append(f(x[i] - eta * df(x[i])))
dt = pd.DataFrame({"X": x, "Y": y})
print(dt)
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.set_xlim(-5, 5)
ax.set_ylim(-45, 45)
ax.plot(t1, f(t1))
ax.plot(x,y,'ro')
X Y 0 -1.000000 6.080605 1 -0.726087 4.418893 2 -0.402500 2.310617 3 -0.084779 0.438219 4 0.182055 -0.845082 5 0.396846 -1.693734 6 0.579732 -2.336309 7 0.751141 -2.930927 8 0.929844 -3.615216 9 1.137943 -4.603376 10 1.410026 -6.413604 11 1.811137 -10.617286 12 2.465952 -21.819727 13 3.481091 -40.258100 14 3.984024 -41.051121 15 3.579914 -41.108070 16 3.934284 -41.401225 17 3.634148 -41.444896 18 3.900044 -41.582657 19 3.670089 -41.614148 20 3.874779 -41.685941
[<matplotlib.lines.Line2D at 0x7f7ed885be20>]
eta = 0.001
x = [-1.0]
y = [f(x[0])]
for i in range(2000):
x.append(x[i] - eta * df(x[i]))
y.append(f(x[i] - eta * df(x[i])))
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.set_xlim(-5, 5)
ax.set_ylim(-45, 45)
ax.plot(t1, f(t1))
ax.plot(x,y,'ro')
[<matplotlib.lines.Line2D at 0x7f7ecc077310>]
Animación
%matplotlib inline
def f(x):
return x * np.cos(x)
t1 = np.arange(-10.0, 15.0, 0.1)
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.set_xlim(-10, 15)
ax.set_ylim(-10, 10)
ax.plot(t1, f(t1))
x = [-1.0]
y = [f(x[0])]
print("X = ", x)
print("Y = ", y)
ax.plot(x,y,'ro')
X = [-1.0] Y = [-0.5403023058681398]
[<matplotlib.lines.Line2D at 0x7f7eb82b5d30>]
# La derivada de f (la pendiente)
def df(x):
return np.cos(x) - x * np.sin(x)
eta = 0.05
x = [-9.0]
y = [f(x[0])]
for i in range(20):
x.append(x[i] - eta * df(x[i]))
y.append(f(x[i] - eta * df(x[i])))
dt = pd.DataFrame({"X": x, "Y": y})
print(dt)
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.set_xlim(-10, 15)
ax.set_ylim(-10, 10)
ax.plot(t1, f(t1))
ax.plot(x,y,'ro')
X Y 0 -9.000000 8.200172 1 -8.768990 6.950019 2 -8.462002 4.833868 3 -8.086168 1.860673 4 -7.681204 -1.320550 5 -7.311458 -3.774899 6 -7.024193 -5.182370 7 -6.824005 -5.850131 8 -6.691206 -6.141911 9 -6.604350 -6.266659 10 -6.547553 -6.320077 11 -6.510273 -6.343130 12 -6.485703 -6.353157 13 -6.469455 -6.357546 14 -6.458685 -6.359476 15 -6.451533 -6.360327 16 -6.446777 -6.360704 17 -6.443612 -6.360871 18 -6.441505 -6.360945 19 -6.440102 -6.360978 20 -6.439167 -6.360992
[<matplotlib.lines.Line2D at 0x7f7ea8068070>]
eta = 0.05
x = [-4.0]
y = [f(x[0])]
for i in range(20):
x.append(x[i] - eta * df(x[i]))
y.append(f(x[i] - eta * df(x[i])))
dt = pd.DataFrame({"X": x, "Y": y})
print(dt)
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.set_xlim(-10, 15)
ax.set_ylim(-10, 10)
ax.plot(t1, f(t1))
ax.plot(x,y,'ro')
X Y 0 -4.000000 2.614574 1 -4.118678 2.304156 2 -4.261399 1.857360 3 -4.431372 1.228964 4 -4.630383 0.379293 5 -4.857028 -0.700071 6 -5.104551 -1.950893 7 -5.359512 -3.231216 8 -5.603454 -4.358037 9 -5.818453 -5.201356 10 -5.993537 -5.743872 11 -6.127046 -6.052511 12 -6.224077 -6.213208 13 -6.292374 -6.292108 14 -6.339481 -6.329438 15 -6.371567 -6.346698 16 -6.393252 -6.354565 17 -6.407836 -6.358119 18 -6.417614 -6.359715 19 -6.424157 -6.360429 20 -6.428530 -6.360748
[<matplotlib.lines.Line2D at 0x7f7ecc26f970>]
eta = 0.05
x = [6.0]
y = [f(x[0])]
for i in range(20):
x.append(x[i] - eta * df(x[i]))
y.append(f(x[i] - eta * df(x[i])))
dt = pd.DataFrame({"X": x, "Y": y})
print(dt)
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.set_xlim(-10, 15)
ax.set_ylim(-10, 10)
ax.plot(t1, f(t1))
ax.plot(x,y,'ro')
X Y 0 6.000000 5.761022 1 5.868167 5.370012 2 5.704107 4.774152 3 5.506179 3.925994 4 5.277496 2.826133 5 5.027871 1.560019 6 4.773370 0.290906 7 4.532098 -0.812676 8 4.318132 -1.658691 9 4.137995 -2.248280 10 3.991465 -2.634683 11 3.874550 -2.879561 12 3.782093 -3.032471 13 3.709174 -3.127589 14 3.651633 -3.186871 15 3.606131 -3.223984 16 3.570053 -3.247344 17 3.541371 -3.262124 18 3.518510 -3.271523 19 3.500250 -3.277525 20 3.485636 -3.281373
[<matplotlib.lines.Line2D at 0x7f7ecc2cb8e0>]
eta = 0.05
x = [7.0]
y = [f(x[0])]
for i in range(20):
x.append(x[i] - eta * df(x[i]))
y.append(f(x[i] - eta * df(x[i])))
dt = pd.DataFrame({"X": x, "Y": y})
print(dt)
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.set_xlim(-10, 15)
ax.set_ylim(-10, 10)
ax.plot(t1, f(t1))
ax.plot(x,y,'ro')
X Y 0 7.000000 5.277316 1 7.192250 4.419521 2 7.445235 2.959180 3 7.766957 0.675067 4 8.149489 -2.373338 5 8.553863 -5.509771 6 8.913219 -7.772173 7 9.174986 -8.890230 8 9.336838 -9.300759 9 9.427646 -9.427607 10 9.476294 -9.463722 11 9.501829 -9.473638 12 9.515111 -9.476315 13 9.521989 -9.477033 14 9.525544 -9.477225 15 9.527379 -9.477276 16 9.528326 -9.477289 17 9.528814 -9.477293 18 9.529066 -9.477294 19 9.529196 -9.477294 20 9.529263 -9.477294
[<matplotlib.lines.Line2D at 0x7f7ecc2e88e0>]
def f(x,y):
return x*x + 3*y
print("f(-10,10) = ", f(-10,10),"\n")
x = -10
y = 10
x0 = np.array([x,y])
print("x, y : ",x0)
fx0 = f(x0[0],x0[1])
print("fx0:",fx0)
def gradiente_f(x,y):
return np.array([2*x,3])
print("gradiente_f: ", gradiente_f(-10,10))
f(-10,10) = 130 x, y : [-10 10] fx0: 130 gradiente_f: [-20 3]
eta = 0.1
x1 = x0 - eta * gradiente_f(x0[0],x0[1])
print("x, y :", x1, "\tz: ",f(x1[0],x1[1]), "\n")
x2 = x1 - eta * gradiente_f(x1[0],x1[1])
print("x, y :", x2, "\tz: ",f(x2[0],x2[1]), "\n")
x3 = x2 - eta * gradiente_f(x2[0],x2[1])
print("x, y :", x3, "\tz: ",f(x3[0],x3[1]), "\n")
x, y : [-8. 9.7] z: 93.1 x, y : [-6.4 9.4] z: 69.16 x, y : [-5.12 9.1 ] z: 53.514399999999995
Ejemplo con más puntos
eta = 0.1
xi = np.array([x,y])
for i in range(20):
xi = xi - eta * gradiente_f(xi[0],xi[1])
print("x, y :", xi, "\tz: ",f(xi[0],xi[1]))
x, y : [-8. 9.7] z: 93.1 x, y : [-6.4 9.4] z: 69.16 x, y : [-5.12 9.1 ] z: 53.514399999999995 x, y : [-4.096 8.8 ] z: 43.17721599999999 x, y : [-3.2768 8.5 ] z: 36.23741823999999 x, y : [-2.62144 8.2 ] z: 31.47194767359999 x, y : [-2.097152 7.9 ] z: 28.09804651110399 x, y : [-1.6777216 7.6 ] z: 25.614749767106552 x, y : [-1.34217728 7.3 ] z: 23.701439850948187 x, y : [-1.07374182 7. ] z: 22.152921504606837 x, y : [-0.85899346 6.7 ] z: 20.837869762948372 x, y : [-0.68719477 6.4 ] z: 19.672236648286955 x, y : [-0.54975581 6.1 ] z: 18.60223145490365 x, y : [-0.43980465 5.8 ] z: 17.59342813113833 x, y : [-0.35184372 5.5 ] z: 16.62379400392853 x, y : [-0.28147498 5.2 ] z: 15.679228162514256 x, y : [-0.22517998 4.9 ] z: 14.750706024009121 x, y : [-0.18014399 4.6 ] z: 13.832451855365836 x, y : [-0.14411519 4.3 ] z: 12.920769187434134 x, y : [-0.11529215 4. ] z: 12.013292279957843
import plotly.graph_objs as go
import plotly.express as px
def f(x,y):
return x*x + 3*y
def gradiente_f(x,y):
return np.array([2*x,3])
x = -10
y = 10
eta = 0.1
xi = np.array([x,y])
x = []
y = []
z = []
for i in range(60):
xi = xi - eta * gradiente_f(xi[0],xi[1])
x.append(xi[0])
y.append(xi[1])
z.append(f(xi[0],xi[1]))
dataF = pd.DataFrame({"X":x, "Y": y, "Z": z})
#Imprimimos en consola solamente 10
print(dataF.head(n = 10))
#Gráfico
fig = px.scatter_3d(dataF, x='X', y='Y', z='Z',color_discrete_sequence=["red"])
xdata = np.arange(-10, 10, 0.1)
ydata = np.arange(-10, 10, 0.1)
X,Y = np.meshgrid(xdata,ydata)
Z = X**2 + 3*Y
fig.add_trace(go.Surface(
x = X,
y = Y,
z = Z,
opacity = .7, showscale = False,
colorscale='Viridis'
))
fig.show()
X Y Z 0 -8.000000 9.7 93.100000 1 -6.400000 9.4 69.160000 2 -5.120000 9.1 53.514400 3 -4.096000 8.8 43.177216 4 -3.276800 8.5 36.237418 5 -2.621440 8.2 31.471948 6 -2.097152 7.9 28.098047 7 -1.677722 7.6 25.614750 8 -1.342177 7.3 23.701440 9 -1.073742 7.0 22.152922
Funciones Importantes
#########################################
# Ejemplo de optimización de una Función de Costo
# Basado en el trabajo de Mehreen Saeed
# https://stackabuse.com/gradient-descent-in-python-implementation-and-theory
# Se define la función gradient_descent(). En esta función, el ciclo termina cuando:
# 1) El número de iteraciones excede un valor máximo.
# 2) La diferencia entre los valores de la función entre dos iteraciones sucesivas cae por debajo de un cierto umbral.
# Los parámetros se actualizan en cada iteración de acuerdo con el gradiente de la función objetivo.
# La función recibe los siguientes parámetros:
# 1) max_iterations: Número máximo de iteraciones a ejecutar.
# 2) umbral: Se setiene si la diferencia en los valores de la función entre dos iteraciones sucesivas cae por debajo de este umbral.
# 3) w_init: Punto inicial desde donde comenzar el descenso del gradiente.
# 3) obj_func: Función que calcula la función objetivo.
# 5) grad_func: Función que calcula el gradiente de la función.
# 6) extra_param: Parámetros adicionales (si es necesario) para obj_func y grad_func.
# 7) learning_rate: Tamaño del paso para el descenso de gradiente. Debería estar en [0,1]
# 8) momentum: Impulso para usar. Debería estar en [0,1]
def gradient_descent(max_iterations,threshold,w_init,
obj_func,grad_func,extra_param = [],
learning_rate=0.05,momentum=0.8):
w = w_init
w_history = w
f_history = obj_func(w,extra_param)
delta_w = np.zeros(w.shape)
i = 0
diff = 1.0e10
while i<max_iterations and diff>threshold:
delta_w = -learning_rate*grad_func(w,extra_param) + momentum*delta_w
w = w+delta_w
# Almacena la historia of w y f
w_history = np.vstack((w_history,w))
f_history = np.vstack((f_history,obj_func(w,extra_param)))
i+=1
diff = np.absolute(f_history[-1]-f_history[-2])
return w_history,f_history
# w es un vector de pesos y xy el vetor fila de datos (train_data, target)
def grad_mse(w,xy):
(x,y) = xy
(rows,cols) = x.shape
# Calcula la salida
o = np.sum(x*w,axis=1)
diff = y-o
diff = diff.reshape((rows,1))
diff = np.tile(diff, (1, cols))
grad = diff*x
grad = -np.sum(grad,axis=0)
return grad
# w es un vector de pesos y xy el vector fila de datos (train_data, target)
def mse(w,xy):
(x,y) = xy
# Calcula la salida usando el mse
o = np.sum(x*w,axis=1)
mse = np.sum((y-o)*(y-o))
mse = mse/2
return mse
Este dataset consiste en una codificación de imágenes 8x8 pixéles de digitos escritos a mano. Cada fila es una imágen, es decir, un dígito. En estos datos encontramos únicamente registros para los dígitos 0 y 1, si desea obtener los datos completos puede acceder a ellos mediante la función load_digits() de la biblioteca sklearn.datasets.
Para más información consulte la documentación.
# Para ilustrar el descenso de gradiente en un problema de clasificación,
#hemos elegido los conjuntos de datos de dígitos incluidos en sklearn.datasets.
# Cargamos los datos
datos = pd.read_csv("digitos_AMano.csv", header=0, index_col=None, decimal=".", sep = ";")
print(datos.shape)
datos.head()
(360, 65)
| pixel_0_0 | pixel_0_1 | pixel_0_2 | pixel_0_3 | pixel_0_4 | pixel_0_5 | pixel_0_6 | pixel_0_7 | pixel_1_0 | pixel_1_1 | ... | pixel_6_7 | pixel_7_0 | pixel_7_1 | pixel_7_2 | pixel_7_3 | pixel_7_4 | pixel_7_5 | pixel_7_6 | pixel_7_7 | digito | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.0 | 0.0 | 5.0 | 13.0 | 9.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 6.0 | 13.0 | 10.0 | 0.0 | 0.0 | 0.0 | 0 |
| 1 | 0.0 | 0.0 | 0.0 | 12.0 | 13.0 | 5.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 11.0 | 16.0 | 10.0 | 0.0 | 0.0 | 1 |
| 2 | 0.0 | 0.0 | 1.0 | 9.0 | 15.0 | 11.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 1.0 | 10.0 | 13.0 | 3.0 | 0.0 | 0.0 | 0 |
| 3 | 0.0 | 0.0 | 0.0 | 0.0 | 14.0 | 13.0 | 1.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 13.0 | 16.0 | 1.0 | 0.0 | 1 |
| 4 | 0.0 | 0.0 | 3.0 | 13.0 | 11.0 | 7.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 2.0 | 12.0 | 13.0 | 4.0 | 0.0 | 0.0 | 0 |
5 rows × 65 columns
Separamos las variables predictoras de la variable a predecir
Y = datos["digito"].ravel()
X = datos.drop(columns=["digito"]).to_numpy()
Ejemplo para graficar una imagen de los dígitos
# Graficas imágenes de los dígitos
fig, ax = plt.subplots(nrows=1, ncols=10, figsize = (10,8), dpi = 200,
subplot_kw=dict(xticks=[], yticks=[]))
for i in np.arange(10):
ax[i].imshow(X[i,:].reshape(8,8),cmap=plt.cm.gray)
# Separa train y test set
x_train, x_test, y_train, y_test = train_test_split(
X, Y, test_size=0.2, random_state=10)
# Agrega la columna de unos de al regresión (bias) en train and test
x_train = np.hstack((np.ones((y_train.size,1)),x_train))
x_test = np.hstack((np.ones((y_test.size,1)),x_test))
# Inicializa los pesos y llama a gradient_descent
rand = np.random.RandomState(19)
w_init = rand.uniform(-1,1,x_train.shape[1])*.000001
w_history,mse_history = gradient_descent(100,0.1,w_init,
mse,grad_mse,(x_train,y_train),
learning_rate=1e-6,momentum=0.7)
# Grafica el MSE
fig, ax = plt.subplots(1,1, figsize = figsize, dpi = dpi)
ax.plot(np.arange(mse_history.size),mse_history)
ax.set_xlabel('Número de Iteración')
ax.set_ylabel('Error Cuadrático Medio')
ax.set_title('Descenso del gradiente para la función de costo - Ejemplo de Dígitos')
Text(0.5, 1.0, 'Descenso del gradiente para la función de costo - Ejemplo de Dígitos')